package com.chris.cc.user.service.impl;

import com.chris.cc.user.config.RedisTokenStore;
import com.chris.cc.user.model.vo.OnlineUserVO;
import com.chris.cc.user.model.vo.UserVO;
import com.chris.cc.user.service.OnlineUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * Copyright (c) 2018-2025, chris All rights reserved.
 * <p>
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * <p>
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * Neither the name of the pig4cloud.com developer nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * <p>
 * Author: haoka (haokang207@126.com)
 * <p>
 * Date: 2018/10/8 16:37
 **/
@Service
public class OnlineUserServiceImpl implements OnlineUserService {

    @Autowired
    private StringRedisTemplate template;
    @Autowired
    private RedisConnectionFactory connectionFactory;
    private RedisTokenStore redisTokenStore;

    @PostConstruct
    public void init() {
        redisTokenStore = new RedisTokenStore(connectionFactory);
    }

    /**
     * 查询所有AccessToken
     *
     * @return
     */
    @Override
    public List<String> queryAllKey() {
        Set<String> keys = template.keys(redisTokenStore.getPrefix() + "access:*");
        if (keys == null || keys.isEmpty()) {
            return Collections.emptyList();
        }
        int prefixLength = (redisTokenStore.getPrefix() + "access:").length();
        return keys.stream()
                .map(key -> {
                    return key.substring(prefixLength);
                })
                .sorted()
                .collect(Collectors.toList());
    }

    /**
     * 查询
     *
     * @param key
     * @return
     */
    @Override
    public OnlineUserVO get(String key) {
        //DefaultOAuth2AccessToken
        OAuth2AccessToken accessToken = redisTokenStore.readAccessToken(key);
        OnlineUserVO onlineUser = new OnlineUserVO();
        onlineUser.setAccessToken(key);
        if (accessToken == null) {
            onlineUser.setRemainingSeconds(0);
            UserVO user = new UserVO();
            onlineUser.setUser(user);
        } else {
            onlineUser.setRemainingSeconds(accessToken.getExpiresIn());
            OAuth2Authentication authentication = redisTokenStore.readAuthentication(accessToken);
            User user = (User) authentication.getPrincipal();
            onlineUser.setTel(user.getUsername());
        }
        return onlineUser;
    }

    /**
     * 删除
     *
     * @param key
     */
    @Override
    public void delete(String key) {
        OAuth2AccessToken accessToken = redisTokenStore.readAccessToken(key);
        if (accessToken != null) {
            redisTokenStore.removeAccessToken(key);
            redisTokenStore.removeRefreshToken(accessToken.getRefreshToken());
        }
    }
}
